Option Strict Off
Option Explicit On
Friend Class clsFTP
	Private Const MAX_PATH As Short = 260
	Private Const INTERNET_FLAG_RELOAD As Integer = &H80000000
	Private Const NO_ERROR As Short = 0
	Private Const FILE_ATTRIBUTE_READONLY As Integer = &H1
	Private Const FILE_ATTRIBUTE_HIDDEN As Integer = &H2
	Private Const FILE_ATTRIBUTE_SYSTEM As Integer = &H4
	Private Const FILE_ATTRIBUTE_DIRECTORY As Integer = &H10
	Private Const FILE_ATTRIBUTE_ARCHIVE As Integer = &H20
	Private Const FILE_ATTRIBUTE_NORMAL As Integer = &H80
	Private Const FILE_ATTRIBUTE_TEMPORARY As Integer = &H100
	Private Const FILE_ATTRIBUTE_COMPRESSED As Integer = &H800
	Private Const FILE_ATTRIBUTE_OFFLINE As Integer = &H1000
	Private Const INTERNET_FLAG_PASSIVE As Integer = &H8000000
	Private Const FORMAT_MESSAGE_FROM_HMODULE As Integer = &H800
	Private Const GENERIC_READ As Integer = &H80000000
	Private Const GENERIC_WRITE As Integer = &H40000000
	Private Sec As Short
	Private Min As Short
	Private Hr As Short
	Private Structure WIN32_FIND_DATA
		Dim dwFileAttributes As Integer
		Dim ftCreationTime As Decimal
		Dim ftLastAccessTime As Decimal
		Dim ftLastWriteTime As Decimal
		Dim nFileSizeHigh As Integer
		Dim nFileSizeLow As Integer
		Dim dwReserved0 As Integer
		Dim dwReserved1 As Integer
		'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
		<VBFixedString(MAX_PATH),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=MAX_PATH)> Public cFileName() As Char
		'UPGRADE_WARNING: Fixed-length string size must fit in the buffer. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="3C1E4426-0B80-443E-B943-0627CD55D48B"'
		<VBFixedString(14),System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray,SizeConst:=14)> Public cAlternate() As Char
	End Structure
	
	Private Const ERROR_NO_MORE_FILES As Short = 18
	Private Const INTERNET_OPEN_TYPE_PRECONFIG As Short = 0
	Private Const INTERNET_INVALID_PORT_NUMBER As Short = 0
	Private Const INTERNET_SERVICE_FTP As Short = 1
	Private Const FTP_TRANSFER_TYPE_BINARY As Integer = &H2
	Private Const FTP_TRANSFER_TYPE_ASCII As Integer = &H1
	
	'UPGRADE_ISSUE: Declaring a parameter 'As Any' is not supported. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="FAE78A8D-8978-4FD4-8208-5B7324A8F795"'
	'UPGRADE_ISSUE: Declaring a parameter 'As Any' is not supported. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="FAE78A8D-8978-4FD4-8208-5B7324A8F795"'
	Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (ByRef lpFileTime As Any, ByRef lpLocalFileTime As Any) As Integer
	
	Private Declare Function FormatMessage Lib "kernel32"  Alias "FormatMessageA"(ByVal dwFlags As Integer, ByVal lpSource As Integer, ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByVal lpBuffer As String, ByVal nSize As Integer, ByRef Arguments As Integer) As Integer
	Private Declare Function FTPGetFile Lib "wininet.dll"  Alias "FtpGetFileA"(ByVal hFtpSession As Integer, ByVal lpszRemoteFile As String, ByVal lpszNewFile As String, ByVal fFailIfExists As Boolean, ByVal dwFlagsAndAttributes As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
	Private Declare Function FtpRenameFile Lib "wininet.dll"  Alias "FtpRenameFileA"(ByVal hFtpSession As Integer, ByVal lpszOldName As String, ByVal lpszNewName As String) As Boolean
	Private Declare Function FtpCreateDirectory Lib "wininet.dll"  Alias "FtpCreateDirectoryA"(ByVal hFtpSession As Integer, ByVal lpszName As String) As Boolean
	Private Declare Function FtpRemoveDirectory Lib "wininet.dll"  Alias "FtpRemoveDirectoryA"(ByVal hFtpSession As Integer, ByVal lpszName As String) As Boolean
	
	Private Declare Function FtpDeleteFile Lib "wininet.dll"  Alias "FtpDeleteFileA"(ByVal hFtpSession As Integer, ByVal lpszFileName As String) As Boolean
	Private Declare Function FtpOpenFile Lib "wininet.dll"  Alias "FtpOpenFileA"(ByVal hFtpSession As Integer, ByVal sBuff As String, ByVal Access As Integer, ByVal Flags As Integer, ByVal Context As Integer) As Integer
	Private Declare Function FTPPutFile Lib "wininet.dll"  Alias "FtpPutFileA"(ByVal hFtpSession As Integer, ByVal lpszLocalFile As String, ByVal lpszRemoteFile As String, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Boolean
	Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll"  Alias "FtpSetCurrentDirectoryA"(ByVal hFtpSession As Integer, ByVal lpszDirectory As String) As Boolean
	Private Declare Function FtpGetCurrentDirectory Lib "wininet.dll"  Alias "FtpGetCurrentDirectoryA"(ByVal hFtpSession As Integer, ByVal lpszCurrentDirectory As String, ByRef lpdwCurrentDirectory As Integer) As Boolean
	'UPGRADE_WARNING: Structure WIN32_FIND_DATA may require marshalling attributes to be passed as an argument in this Declare statement. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="C429C3A5-5D47-4CD9-8F51-74A1616405DC"'
	Private Declare Function FtpFindFirstFile Lib "wininet.dll"  Alias "FtpFindFirstFileA"(ByVal hFtpSession As Integer, ByVal lpszSearchFile As String, ByRef lpFindFileData As WIN32_FIND_DATA, ByVal dwFlags As Integer, ByVal dwContent As Integer) As Integer
	
	Private Declare Function GetModuleHandle Lib "kernel32"  Alias "GetModuleHandleA"(ByVal lpLibFileName As String) As Integer
	
	'UPGRADE_WARNING: Structure WIN32_FIND_DATA may require marshalling attributes to be passed as an argument in this Declare statement. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="C429C3A5-5D47-4CD9-8F51-74A1616405DC"'
	Private Declare Function InternetFindNextFile Lib "wininet.dll"  Alias "InternetFindNextFileA"(ByVal hFind As Integer, ByRef lpvFindData As WIN32_FIND_DATA) As Integer
	Private Declare Function InternetWriteFile Lib "wininet.dll" (ByVal hFile As Integer, ByRef sBuffer As Byte, ByVal lNumBytesToWrite As Integer, ByRef dwNumberOfBytesWritten As Integer) As Short
	Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Integer, ByRef sBuffer As Byte, ByVal lNumBytesToRead As Integer, ByRef dwNumberOfBytesRead As Integer) As Short
	Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Integer) As Integer
	Private Declare Function InternetOpen Lib "wininet.dll"  Alias "InternetOpenA"(ByVal sAgent As String, ByVal lAccessType As Integer, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Integer) As Integer
	Private Declare Function InternetConnect Lib "wininet.dll"  Alias "InternetConnectA"(ByVal hInternetSession As Integer, ByVal sServerName As String, ByVal nServerPort As Short, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Integer, ByVal lFlags As Integer, ByVal lContext As Integer) As Integer
	Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll"  Alias "InternetGetLastResponseInfoA"(ByRef lpdwError As Integer, ByVal lpszErrorBuffer As String, ByRef lpdwErrorBufferLength As Integer) As Boolean
	
	Private Const rDayZeroBias As Double = 109205# ' Abs(CDbl(#01-01-1601#))
	Private Const rMillisecondPerDay As Double = 10000000# * 60# * 60# * 24# / 10000#
	
	Private Const BUFFERSIZE As Short = 255
	
	Private hOpen As Integer
	Private hConnection As Integer
	Private hFile As Integer
	Private dwType As Integer
	Private dwSeman As Integer
	
	Private szErrorMessage As String
	
	Private mDirCol As New cDirList
	
	Public Enum FTP_CONNECTION_STATES
		FTP_CONNECTION_RESOLVING_HOST
		FTP_CONNECTION_HOST_RESOLVED
		FTP_CONNECTION_CONNECTED
		FTP_CONNECTION_AUTHENTICATION
		FTP_USER_LOGGED
		FTP_ESTABLISHING_DATA_CONNECTION
		FTP_DATA_CONNECTION_ESTABLISHED
		FTP_RETRIEVING_DIRECTORY_INFO
		FTP_DIRECTORY_INFO_COMPLETED
		FTP_TRANSFER_STARTING
		FTP_TRANSFER_COMLETED
	End Enum
	'all possible reply codes that can be sent by ftp server
	Private Enum FTP_RESPONSE_CODES
		FTP_RESPONSE_RESTART_MARKER_REPLY = 110
		FTP_RESPONSE_SERVICE_READY_IN_MINUTES = 120
		FTP_RESPONSE_DATA_CONNECTION_ALREADY_OPEN = 125
		FTP_RESPONSE_FILE_STATUS_OK = 150
		FTP_RESPONSE_COMMAND_OK = 200
		FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS_AT_THIS_SITE = 202 'superfluous at this site
		FTP_RESPONSE_SYSTEM_STATUS_OR_SYSTEM_HELP_REPLY = 211
		FTP_RESPONSE_DIRECTORY_STATUS = 212
		FTP_RESPONSE_FILE_STATUS = 213
		FTP_RESPONSE_HELP_MESSAGE = 214
		FTP_RESPONSE_NAME_SYSTEM_TYPE = 215
		FTP_RESPONSE_SERVICE_READY_FOR_NEW_USER = 220
		FTP_RESPONSE_SERVICE_CLOSING_CONTROL_CONNECTION = 221
		FTP_RESPONSE_DATA_CONNECTION_OPEN = 225
		FTP_RESPONSE_CLOSING_DATA_CONNECTION = 226
		FTP_RESPONSE_ENTERING_PASSIVE_MODE = 227
		FTP_RESPONSE_USER_LOGGED_IN = 230
		FTP_RESPONSE_REQUESTED_FILE_ACTION_OK_COMPLETED = 250
		FTP_RESPONSE_PATHNAME_CREATED = 257
		FTP_RESPONSE_USER_NAME_OK_NEED_PASSWORD = 331
		FTP_RESPONSE_NEED_ACCOUNT_FOR_LOGIN = 332
		FTP_RESPONSE_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO = 350
		FTP_RESPONSE_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION = 421
		FTP_RESPONSE_CANNOT_OPEN_DATA_CONNECTION = 425
		FTP_RESPONSE_CONNECTION_CLOSED_TRANSFER_ABORTED = 426
		FTP_RESPONSE_REQUESTED_FILE_ACTION_NOT_TAKEN = 450
		FTP_RESPONSE_REQUESTED_ACTION_ABORTED = 451
		FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN = 452
		FTP_RESPONSE_SYNTAX_ERROR_COMMAND_UNRECOGNIZED = 500
		FTP_RESPONSE_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS = 501
		FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED = 502
		FTP_RESPONSE_BAD_SEQUENCE_OF_COMMANDS = 503
		FTP_RESPONSE_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER = 504
		FTP_RESPONSE_NOT_LOGGED_IN = 530
		FTP_RESPONSE_NEED_ACCOUNT_FOR_STORING_FILES = 532
		FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE = 550
		FTP_RESPONSE_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN = 551
		FTP_RESPONSE_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION = 552
		FTP_RESPONSE_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED = 553
	End Enum
	Public Enum FtpErrors
		ERROR_FTP_WINSOCK_AddressInUse
		ERROR_FTP_WINSOCK_AddressNotAvailable
		ERROR_FTP_WINSOCK_AlreadyComplete
		ERROR_FTP_WINSOCK_AlreadyConnected
		ERROR_FTP_WINSOCK_BadState
		ERROR_FTP_WINSOCK_ConnectAborted
		ERROR_FTP_WINSOCK_ConnectionRefused
		ERROR_FTP_WINSOCK_ConnectionReset
		ERROR_FTP_WINSOCK_GetNotSupported
		ERROR_FTP_WINSOCK_HostNotFound
		ERROR_FTP_WINSOCK_HostNotFoundTryAgain
		ERROR_FTP_WINSOCK_InProgress
		ERROR_FTP_WINSOCK_InvalidArg
		ERROR_FTP_WINSOCK_InvalidArgument
		ERROR_FTP_WINSOCK_InvalidOp
		ERROR_FTP_WINSOCK_InvalidPropertyValue
		ERROR_FTP_WINSOCK_MsgTooBig
		ERROR_FTP_WINSOCK_NetReset
		ERROR_FTP_WINSOCK_NetworkSubsystemFailed
		ERROR_FTP_WINSOCK_NetworkUnreachable
		ERROR_FTP_WINSOCK_NoBufferSpace
		ERROR_FTP_WINSOCK_NoData
		ERROR_FTP_WINSOCK_NonRecoverableError
		ERROR_FTP_WINSOCK_NotConnected
		ERROR_FTP_WINSOCK_NotInitialized
		ERROR_FTP_WINSOCK_NotSocket
		ERROR_FTP_WINSOCK_OpCanceled
		ERROR_FTP_WINSOCK_OutOfMemory
		ERROR_FTP_WINSOCK_OutOfRange
		ERROR_FTP_WINSOCK_PortNotSupported
		ERROR_FTP_WINSOCK_SetNotSupported
		ERROR_FTP_WINSOCK_SocketShutdown
		ERROR_FTP_WINSOCK_Success
		ERROR_FTP_WINSOCK_Timedout
		ERROR_FTP_WINSOCK_Unsupported
		ERROR_FTP_WINSOCK_WouldBlock
		ERROR_FTP_WINSOCK_WrongProtocol
		ERROR_FTP_PROTOCOL_SERVICE_READY_IN_MINUTES
		ERROR_FTP_PROTOCOL_USER_NAME_OK_NEED_PASSWORD
		ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_LOGIN
		ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_PENDING_FURTHER_INFO
		ERROR_FTP_PROTOCOL_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION
		ERROR_FTP_PROTOCOL_CANNOT_OPEN_DATA_CONNECTION
		ERROR_FTP_PROTOCOL_CONNECTION_CLOSED_TRANSFER_ABORTED
		ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_NOT_TAKEN
		ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED
		ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN
		ERROR_FTP_PROTOCOL_SYNTAX_ERROR_COMMAND_UNRECOGNIZED
		ERROR_FTP_PROTOCOL_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS
		ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED
		ERROR_FTP_PROTOCOL_BAD_SEQUENCE_OF_COMMANDS
		ERROR_FTP_PROTOCOL_COMMAND_NOT_IMPLEMENTED_FOR_THAT_PARAMETER
		ERROR_FTP_PROTOCOL_NOT_LOGGED_IN
		ERROR_FTP_PROTOCOL_NEED_ACCOUNT_FOR_STORING_FILES
		ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_UNAVAILABLE
		ERROR_FTP_PROTOCOL_REQUESTED_ACTION_ABORTED_PAGE_TYPE_UNKNOWN
		ERROR_FTP_PROTOCOL_REQUESTED_FILE_ACTION_ABORTED_EXCEEDED_STORAGE_ALLOCATION
		ERROR_FTP_PROTOCOL_REQUESTED_ACTION_NOT_TAKEN_FILE_NAME_NOT_ALLOWED
		ERROR_FTP_USER_TIMEOUT
		ERROR_FTP_USER_TRANSFER_IN_PROGRESS
	End Enum
	Public Event StateChanged(ByRef State As FTP_CONNECTION_STATES)
	Public Event FileTransferProgress(ByRef lCurrentBytes As Integer, ByRef lTotalBytes As Integer)
	
	Private Function Win32ToVbTime(ByRef ft As Decimal) As Date
		Dim ftl As Decimal
		' Call API to convert from UTC time to local time
		If FileTimeToLocalFileTime(ft, ftl) Then
			' Local time is nanoseconds since 01-01-1601
			' In Currency that comes out as milliseconds
			' Divide by milliseconds per day to get days since 1601
			' Subtract days from 1601 to 1899 to get VB Date equivalent
			Win32ToVbTime = System.Date.FromOADate((ftl / rMillisecondPerDay) - rDayZeroBias)
		Else
			MsgBox(Err.LastDllError)
		End If
	End Function
	
	ReadOnly Property Directory() As cDirList
		Get
			Directory = mDirCol
		End Get
	End Property
	
	ReadOnly Property GetLastErrorMessage() As String
		Get
			GetLastErrorMessage = szErrorMessage
		End Get
	End Property
	
	Private Sub ErrorOut(ByVal dwError As Integer, ByRef szFunc As String)
		Dim dwRet As Integer
		Dim dwTemp As Integer
		Dim szString As New VB6.FixedLengthString(2048)
		dwRet = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle("wininet.dll"), dwError, 0, szString.Value, 256, 0)
		szErrorMessage = szFunc & " error code: " & dwError & " Message: " & Trim(szString.Value)
		If (dwError = 12003) Then
			' Extended error information was returned
			dwRet = InternetGetLastResponseInfo(dwTemp, szString.Value, 2048)
			szErrorMessage = Trim(szString.Value)
		End If
		Debug.Print(szErrorMessage)
	End Sub
	
	Public Sub CloseConnection()
		If hConnection <> 0 Then
			InternetCloseHandle(hConnection)
		End If
		hConnection = 0
	End Sub
	
	Public Function SimpleFTPPutFile(ByRef sLocal As String, ByRef sRemote As String) As Boolean
		If (FTPPutFile(hConnection, sLocal, sRemote, dwType, 0) = False) Then
			ErrorOut(Err.LastDllError, "SimpleFtpPutFile")
			SimpleFTPPutFile = False
			Exit Function
		Else
			SimpleFTPPutFile = True
		End If
	End Function
	
	Public Function RenameFTPFile(ByRef sExisting As String, ByRef sNewName As String) As Boolean
		If (FtpRenameFile(hConnection, sExisting, sNewName) = False) Then
			ErrorOut(Err.LastDllError, "RenameFTPFile")
			RenameFTPFile = False
			Exit Function
		Else
			RenameFTPFile = True
		End If
	End Function
	
	Public Function CreateFTPDirectory(ByRef sDirectory As String) As Boolean
		If (FtpCreateDirectory(hConnection, sDirectory) = False) Then
			ErrorOut(Err.LastDllError, "CreateFTPDirectory")
			CreateFTPDirectory = False
			Exit Function
		Else
			CreateFTPDirectory = True
		End If
	End Function
	
	Public Function RemoveFTPDirectory(ByRef sDirectory As String) As Boolean
		If (FtpRemoveDirectory(hConnection, sDirectory) = False) Then
			ErrorOut(Err.LastDllError, "RemoveFTPDirectory")
			RemoveFTPDirectory = False
			Exit Function
		Else
			RemoveFTPDirectory = True
		End If
	End Function
	
	Public Function DeleteFTPFile(ByRef sRemote As String) As Boolean
		If (FtpDeleteFile(hConnection, sRemote) = False) Then
			ErrorOut(Err.LastDllError, "DeleteFTPFile")
			DeleteFTPFile = False
			Exit Function
		Else
			DeleteFTPFile = True
		End If
	End Function
	
	Public Function OpenConnection(ByRef sServer As String, ByRef sPort As String, ByRef sUser As String, ByRef sPassword As String) As Boolean
		If hConnection <> 0 Then
			InternetCloseHandle(hConnection)
		End If
		
		hConnection = InternetConnect(hOpen, sServer, CShort(sPort), sUser, sPassword, INTERNET_SERVICE_FTP, dwSeman, 0)
		If hConnection = 0 Then
			ErrorOut(Err.LastDllError, "InternetConnect")
			OpenConnection = False
			Exit Function
		Else
			OpenConnection = True
			
		End If
	End Function
	
	Public Function FTPUploadFile(ByRef sLocal As String, ByRef sRemote As String) As Boolean
		Dim Data(BUFFERSIZE - 1) As Byte
		Dim Written As Integer
		Dim Size As Integer
		Dim Sum As Integer
		Dim lBlock As Integer
		
		Sum = 0
		lBlock = 0
		sLocal = Trim(sLocal)
		sRemote = Trim(sRemote)
		
		If sLocal <> "" And sRemote <> "" Then
			hFile = FtpOpenFile(hConnection, sRemote, GENERIC_WRITE, dwType, 0)
			If hFile = 0 Then
				ErrorOut(Err.LastDllError, "FtpOpenFile:PutFile")
				FTPUploadFile = False
				Exit Function
			End If
			
			FileOpen(1, sLocal, OpenMode.Binary, OpenAccess.Read)
			Size = LOF(1)
			For lBlock = 1 To Size \ BUFFERSIZE
				'UPGRADE_WARNING: Get was upgraded to FileGet and has a new behavior. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"'
				FileGet(1, Data)
				If (InternetWriteFile(hFile, Data(0), BUFFERSIZE, Written) = 0) Then
					FTPUploadFile = False
					ErrorOut(Err.LastDllError, "InternetWriteFile")
					Exit Function
				End If
				System.Windows.Forms.Application.DoEvents()
				Sum = Sum + BUFFERSIZE
				RaiseEvent FileTransferProgress(Sum, Size)
			Next lBlock
			
			'UPGRADE_WARNING: Get was upgraded to FileGet and has a new behavior. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"'
			FileGet(1, Data)
			If (InternetWriteFile(hFile, Data(0), Size Mod BUFFERSIZE, Written) = 0) Then
				FTPUploadFile = False
				ErrorOut(Err.LastDllError, "InternetWriteFile2")
				Exit Function
			End If
			
			Sum = Sum + (Size Mod BUFFERSIZE)
			Size = Sum
			RaiseEvent FileTransferProgress(Sum, Size)
			FileClose(1)
			InternetCloseHandle(hFile)
			FTPUploadFile = True
		End If
	End Function
	
	Public Function FTPDownloadFile(ByRef sLocal As String, ByRef sRemote As String) As Boolean
		Dim Data(BUFFERSIZE - 1) As Byte ' array of 100 elements 0 to 99
		Dim Written As Integer
		Dim Size As Integer
		Dim Sum As Integer
		Dim lBlock As Integer
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
		FTPDownloadFile = False
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
		RaiseEvent StateChanged(FTP_CONNECTION_STATES.FTP_TRANSFER_STARTING)
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
		Sum = 0
		lBlock = 0
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
		sLocal = sLocal
		sRemote = sRemote
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
		If sLocal <> "" And sRemote <> "" Then
			Size = GetFTPFileSize(sRemote) ' ===========
			System.Windows.Forms.Application.DoEvents()
			System.Windows.Forms.Application.DoEvents()
			If Size >= 0 Then
				System.Windows.Forms.Application.DoEvents()
				hFile = FtpOpenFile(hConnection, sRemote, GENERIC_READ, dwType, 0)
				
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				If hFile = 0 Then
					ErrorOut(Err.LastDllError, "FtpOpenFile:GetFile")
					Exit Function
				End If
				System.Windows.Forms.Application.DoEvents()
				FileOpen(1, sLocal, OpenMode.Binary, OpenAccess.Write)
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				Seek(1, 1)
				Sum = 1
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				For lBlock = 1 To Size \ BUFFERSIZE
					If (InternetReadFile(hFile, Data(0), BUFFERSIZE, Written) = 0) Then
						ErrorOut(Err.LastDllError, "InternetReadFile")
						FileClose(1)
						Exit Function
					End If
					System.Windows.Forms.Application.DoEvents()
					System.Windows.Forms.Application.DoEvents()
					'UPGRADE_WARNING: Put was upgraded to FilePut and has a new behavior. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"'
					FilePut(1, Data)
					System.Windows.Forms.Application.DoEvents()
					Sum = Sum + BUFFERSIZE
					System.Windows.Forms.Application.DoEvents()
					RaiseEvent FileTransferProgress(Sum, Size)
					System.Windows.Forms.Application.DoEvents()
					System.Windows.Forms.Application.DoEvents()
				Next lBlock
				
				Dim Data2((Size Mod BUFFERSIZE) - 1) As Byte
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				If (InternetReadFile(hFile, Data2(0), Size Mod BUFFERSIZE, Written) = 0) Then
					ErrorOut(Err.LastDllError, "InternetReadFile2")
					FileClose(1)
					System.Windows.Forms.Application.DoEvents()
					System.Windows.Forms.Application.DoEvents()
					Exit Function
				End If
				
				'UPGRADE_WARNING: Put was upgraded to FilePut and has a new behavior. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="9B7D5ADD-D8FE-4819-A36C-6DEDAF088CC7"'
				FilePut(1, Data2)
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				Sum = Sum + (Size Mod BUFFERSIZE)
				Size = Sum
				RaiseEvent FileTransferProgress(Sum, Size)
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				FileClose(1)
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				InternetCloseHandle(hFile)
				FTPDownloadFile = True
				System.Windows.Forms.Application.DoEvents()
				System.Windows.Forms.Application.DoEvents()
				RaiseEvent StateChanged(FTP_CONNECTION_STATES.FTP_TRANSFER_COMLETED)
			End If
		End If
	End Function
	
	Public Function SimpleFTPGetFile(ByRef sLocal As String, ByRef sRemote As String) As Boolean
		' add INTERNET_FLAG_NO_CACHE_WRITE to avoid local caching 0x04000000 (hex)
		If (FTPGetFile(hConnection, sRemote, sLocal, False, FILE_ATTRIBUTE_NORMAL, dwType Or INTERNET_FLAG_RELOAD, 0) = False) Then
			ErrorOut(Err.LastDllError, "SimpleFtpGetFile")
			SimpleFTPGetFile = False
			Exit Function
		Else
			SimpleFTPGetFile = True
		End If
	End Function
	
	Public Function GetFTPDirectory() As String
		Dim szDir As String
		szDir = New String(Chr(0), 1024)
		If (FtpGetCurrentDirectory(hConnection, szDir, 1024) = False) Then
			ErrorOut(Err.LastDllError, "FtpGetCurrentDirectory")
			Exit Function
		Else
			GetFTPDirectory = Left(szDir, InStr(1, szDir, New String(Chr(0), 1), CompareMethod.Binary) - 1)
		End If
	End Function
	
	Public Function SetFTPDirectory(ByRef sDir As String) As Object
		If (FtpSetCurrentDirectory(hConnection, sDir) = False) Then
			ErrorOut(Err.LastDllError, "FtpSetCurrentDirectory")
			'UPGRADE_WARNING: Couldn't resolve default property of object SetFTPDirectory. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"'
			SetFTPDirectory = False
			Exit Function
		Else
			'UPGRADE_WARNING: Couldn't resolve default property of object SetFTPDirectory. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6A50421D-15FE-4896-8A1B-2EC21E9037B2"'
			SetFTPDirectory = True
		End If
	End Function
	
	Public Function GetFTPFileSize(ByRef sFile As String) As Integer
		Dim szDir As String
		Dim hFind As Integer
		Dim nLastError As Integer
		Dim pData As WIN32_FIND_DATA
		
		hFind = FtpFindFirstFile(hConnection, sFile, pData, 0, 0)
		nLastError = Err.LastDllError
		If hFind = 0 Then
			If (nLastError = ERROR_NO_MORE_FILES) Then
				GetFTPFileSize = -1 ' File not found
				Debug.Print("File Not Found : FtpFindFirstFile")
			Else
				GetFTPFileSize = -2 ' Other error
				ErrorOut(Err.LastDllError, "FtpFindFirstFile")
			End If
		End If
		GetFTPFileSize = pData.nFileSizeLow
		InternetCloseHandle(hFind)
	End Function
	
	Public Function GetDirectoryListing(ByRef sFilter As String) As cDirList
		Dim szDir As String
		Dim hFind As Integer
		Dim nLastError As Integer
		Dim dError As Integer
		Dim ptr As Integer
		Dim pData As WIN32_FIND_DATA
		Dim sFilename As String
		
		'UPGRADE_NOTE: Object mDirCol may not be destroyed until it is garbage collected. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="6E35BFF6-CD74-4B09-9689-3E1A43DF8969"'
		mDirCol = Nothing
		System.Windows.Forms.Application.DoEvents()
		hFind = FtpFindFirstFile(hConnection, sFilter, pData, 0, 0)
		System.Windows.Forms.Application.DoEvents()
		nLastError = Err.LastDllError
		System.Windows.Forms.Application.DoEvents()
		If hFind = 0 Then
			If (nLastError <> ERROR_NO_MORE_FILES) Then
				ErrorOut(Err.LastDllError, "FtpFindFirstFile")
			End If
			Exit Function
		End If
		
		dError = NO_ERROR
		Dim bRet As Boolean
		
		sFilename = Left(pData.cFileName, InStr(1, pData.cFileName, New String(Chr(0), 1), CompareMethod.Binary) - 1)
		mDirCol.Add(pData.dwFileAttributes, Win32ToVbTime(pData.ftCreationTime), Win32ToVbTime(pData.ftLastAccessTime), Win32ToVbTime(pData.ftLastWriteTime), pData.nFileSizeLow, sFilename)
		Do 
			System.Windows.Forms.Application.DoEvents()
			pData.cFileName = New String(Chr(0), MAX_PATH)
			bRet = InternetFindNextFile(hFind, pData)
			System.Windows.Forms.Application.DoEvents()
			If Not bRet Then
				dError = Err.LastDllError
				If dError = ERROR_NO_MORE_FILES Then
					Exit Do
				Else
					ErrorOut(Err.LastDllError, "InternetFindNextFile")
					InternetCloseHandle(hFind)
					Exit Function
				End If
				System.Windows.Forms.Application.DoEvents()
			Else
				sFilename = Left(pData.cFileName, InStr(1, pData.cFileName, New String(Chr(0), 1), CompareMethod.Binary) - 1)
				mDirCol.Add(pData.dwFileAttributes, Win32ToVbTime(pData.ftCreationTime), Win32ToVbTime(pData.ftLastAccessTime), Win32ToVbTime(pData.ftLastWriteTime), pData.nFileSizeLow, sFilename)
			End If
			System.Windows.Forms.Application.DoEvents()
		Loop 
		System.Windows.Forms.Application.DoEvents()
		GetDirectoryListing = mDirCol
		System.Windows.Forms.Application.DoEvents()
		InternetCloseHandle(hFind)
	End Function
	
	Public Sub SetTransferASCII()
		dwType = FTP_TRANSFER_TYPE_ASCII
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
	End Sub
	
	Public Sub SetTransferBinary()
		dwType = FTP_TRANSFER_TYPE_BINARY
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
	End Sub
	
	Public Sub SetModeActive()
		dwSeman = 0
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
	End Sub
	
	Public Sub SetModePassive()
		dwSeman = INTERNET_FLAG_PASSIVE
		System.Windows.Forms.Application.DoEvents()
		System.Windows.Forms.Application.DoEvents()
	End Sub
	
	'UPGRADE_NOTE: Class_Initialize was upgraded to Class_Initialize_Renamed. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="A9E4979A-37FA-4718-9994-97DD76ED70A7"'
	Private Sub Class_Initialize_Renamed()
		hOpen = InternetOpen("SMC FTP Client", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
		If hOpen = 0 Then
			ErrorOut(Err.LastDllError, "InternetOpen")
		End If
		dwType = FTP_TRANSFER_TYPE_ASCII
		dwSeman = 0
		hConnection = 0
	End Sub
	Public Sub New()
		MyBase.New()
		Class_Initialize_Renamed()
	End Sub
	
	'UPGRADE_NOTE: Class_Terminate was upgraded to Class_Terminate_Renamed. Click for more: 'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="A9E4979A-37FA-4718-9994-97DD76ED70A7"'
	Private Sub Class_Terminate_Renamed()
		InternetCloseHandle(hOpen)
	End Sub
	Protected Overrides Sub Finalize()
		Class_Terminate_Renamed()
		MyBase.Finalize()
	End Sub
End Class